use core::cmp::Ordering;
use core::fmt::Debug;

// ParticalOrd是core中定义的trait
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

#[derive(Debug,Clone)]
struct Person {
    name: String,
    age: u32
}

impl PartialEq for Person {
    fn eq(&self, other: &Person) -> bool {
        self.age == other.age && self.name.eq(&other.name)
    }
    fn ne(&self, other: &Person) -> bool {
        self.age != other.age || self.name.ne(&other.name)
    }
}

impl PartialOrd for Person {
    fn partial_cmp(&self, other: &Person) -> Option<Ordering> {
        self.age.partial_cmp(&other.age)
    }
}

fn cmp_demo() {
    let a = 2.0;
    let b = 1.0;
    // 因为基本类型已经实现了这些trait
    let result = a.partial_cmp(&b);
    println!("result:{:?}", result);
}

// trait，特性，接口集
// 内部声明的是函数原型
pub trait Summary {
    fn summarize(&self) -> String;
    fn say_hello(&self);
}

pub struct Article {
    pub headline: String,
    pub author: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        self.say_hello();
        format!("{}, by {}", self.headline, self.author)
    }

    fn say_hello(&self) {
        println!("hello from article");
    }
}

// 可以作为参数
fn trait_as_param(s: &impl Summary) {
    println!("Summary: {}", s.summarize());
}

// 第2种写法。
pub fn notify<T: Summary>(item: &T) {
    println!("Breaking news: {}", item.summarize());
}

struct Student<T: Clone + Debug> {
    name: String,
    person: T,
}

// 补充带有泛型的struct
impl<T: Clone+Debug> Student<T> {

    // Student 中引用了泛型，可以直接使用，不需要在函数中声明。
    fn say(&self) {
        println!("hello person: {:?}", self.person);
        let p = Student{name:"lin".to_string(), person:32_i32};
        let t: &T = &self.person;
        println!("hello person: {:?}", t);
        p.say2();
    }

    fn say2(&self) {
        println!("hello person: {:?}", self.person);
    }
}


fn main() {
    let numbers:Vec<i32> = vec![34, 50, 80, 21, 100];

    let largest = largest(&numbers);

    println!("largest: {}", largest);

    let a = &Article{
        headline: String::from("Hello world"),
        author: String::from("linlin")
    };
    // t::m方式调用
    Summary::summarize(a);
    println!("Article summarize: {}", a.summarize());
    trait_as_param(a);
    notify(a);
    cmp_demo();
    let p = Person{name: "lin".to_string(), age: 31};
    let s = Student{name:"lin2".to_string(), person: p};
    s.say();
}
